#include "user_threads.h"
#include "user_mutex.h"

#include <assert.h>
#include <stdio.h>
#include <stdbool.h>
#include "sieve.h"

#define VERIFY(cmd, expected)                                           \
	do { \
	int ret = -1; \
	ret = cmd; \
	assert(expected == ret); \
	} while (0)

static int thread_bomb(void * arg);

static void last_thread()
{
	int i = -1;
	VERIFY(uthread_create(thread_bomb, NULL, UTHREAD_MIN_PRIO),
	       UTHREAD_FAIL);
	for (i = 1; i < uthread_self(); ++i) {
		VERIFY(uthread_cancel(i), UTHREAD_SUCCESS);
	}
	for (i = 1; i < uthread_self(); ++i) {
		/* can't kill vampires or zombies */
		VERIFY(uthread_cancel(i), UTHREAD_FAIL);
	}
	VERIFY(uthread_create(thread_bomb, NULL, UTHREAD_MIN_PRIO),
	       UTHREAD_FAIL);
}

static void bomb_thread()
{
	uthread_id tid = -1;
	int retval = -1;
	tid = uthread_create(thread_bomb, NULL, UTHREAD_MIN_PRIO);
	assert(tid != UTHREAD_FAIL);
	VERIFY(uthread_join(tid, &retval), UTHREAD_SUCCESS);
	assert(false);
}

static int thread_bomb(void * arg)
{
	if (uthread_self() == (UTHREAD_MAX_THREADS - 1))
		last_thread();
	else
		bomb_thread();
	return 34;
}

int main(int argc, char ** argv)
{
	uthread_id tid = -1;
	int retval = -1;
	uthread_init();
	tid = uthread_create(thread_bomb, NULL, UTHREAD_MIN_PRIO);
	assert(tid != UTHREAD_FAIL);
	VERIFY(uthread_join(tid, &retval), UTHREAD_SUCCESS);
	assert(retval == UTHREAD_CANCELLED);
	printf("Test passed.\n");
	return 0;
}
